package com.everflourish.yeah100.utils.bluetooth;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.everflourish.yeah100.utils.LogUtil;
import com.everflourish.yeah100.utils.constant.SheetType;
import com.everflourish.yeah100.utils.markingsystem.Parse40x16Util;
import com.everflourish.yeah100.utils.markingsystem.Parse56x16Util;
import com.everflourish.yeah100.utils.markingsystem.Parse61x16Util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

@SuppressLint("DefaultLocale")
public class BluetoothHelper {

    public static final String TAG = "BluetoothService";
    protected static final int CONN_BLUETOOTH_STATUS = 0;
    protected static final int CONN_BLUETOOTH_FAILURE = 1;
    protected static final int READ_CARD_SUCCESS = 3;
    protected static final int READ_CARD_FAILURE = 4;
    protected static final int NOT_FOUND_SHEET = 5;
    protected static final String SHEET_DATA = "sheetData";
    protected static final String SHEET_TYPE = "sheetType";

    private static BluetoothHelper mBluetoothHelper;
    private Context mContext;

    private BluetoothAdapter mBluetoothAdapter;
    public String mTargetAddress = null;
    private boolean isOpenBroadcast = false;
    public BluetoothDevice mConnDevice;
    public boolean isConn = false;
    public boolean mReadable = false; // 是否可读

    private BluetoothConnector.BluetoothSocketWrapper mBluetoothSocket;
    private ReadThread mReadThread;
    private InputStream mInputStream;
    // 配对成功蓝牙集合
    private List<BluetoothDevice> mPairedDevices;
    private List<BluetoothDevice> mNewDevices;

    // --------接口回调------------------
    IReadCard iReadCard;
    IBluetoothSearch iBluetoothSearch;
    IBluetoothStatus iBluetoothStatus;

    private boolean isCloseBluetooth = false;

    /**
     * 是否是断开蓝牙操作
     *
     * @return
     */
    public boolean isCloseBluetooth() {
        return isCloseBluetooth;
    }

    public void setCloseBluetooth(boolean isCloseBluetooth) {
        this.isCloseBluetooth = isCloseBluetooth;
    }

    private BluetoothHelper(Context context) {
        mContext = context;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        IntentFilter requestFilter = new IntentFilter(
                BluetoothAdapter.ACTION_STATE_CHANGED);
        mContext.registerReceiver(mBluetoothChange, requestFilter);
    }

    /**
     * 获取实例，单例模式
     *
     * @return
     */
    public static BluetoothHelper getInstance(Context context) {
        if (mBluetoothHelper == null) {
            mBluetoothHelper = new BluetoothHelper(context);
        }
        return mBluetoothHelper;
    }

    /**
     * 设置读卡监听
     *
     * @param iReadCard
     */
    public void setOnReadCardListener(IReadCard iReadCard) {
        this.iReadCard = iReadCard;
    }

    /**
     * 设置蓝牙搜索监听
     *
     * @param iBluetoothSearch
     */
    public void setOnBluetoothSearchListener(IBluetoothSearch iBluetoothSearch) {
        this.iBluetoothSearch = iBluetoothSearch;
    }

    /**
     * 设置蓝牙连接状态监听
     *
     * @param iBluetoothStatus
     */
    public void setOnBluetoothStatusListener(IBluetoothStatus iBluetoothStatus) {
        this.iBluetoothStatus = iBluetoothStatus;
    }

    /**
     * 开启蓝牙
     *
     * @param act
     */
    private void openBluetooth(Activity act) {
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        act.startActivityForResult(enableIntent, 3);
    }

    public void connect(String targetAddress) {
        mConnDevice = mBluetoothAdapter.getRemoteDevice(targetAddress);
        ClientThread clientThread = new ClientThread();
        clientThread.start();
    }

    /**
     * 连接蓝牙
     *
     * @param act
     */
    public void connectBluetooth(Activity act) {
        if (!isConn) {// 去连接
            bluetoothInit(act);
        } else {
            Toast.makeText(mContext, "蓝牙已经连接!", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 断开蓝牙连接
     */
    public void closeConnectBluetooth() {
        try {
            if (mBluetoothAdapter != null) {
                mBluetoothAdapter.cancelDiscovery();
            }
            if (isOpenBroadcast) {
                mContext.unregisterReceiver(mReceiver);
                isOpenBroadcast = false;
            }
            shutdownClient();
            isConn = false;
            if (mTimer != null) {
                mTimer.cancel();
            }
            handler.sendEmptyMessage(CONN_BLUETOOTH_STATUS);
        } catch (Exception e) {
            Log.e(TAG, "断开蓝牙连接发生异常", e);
        }
    }

    /**
     * 取消蓝牙搜索
     */
    public void cancleDiscovery() {
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
        if (isOpenBroadcast) {
            mContext.unregisterReceiver(mReceiver);
            isOpenBroadcast = false;
        }
    }

    /**
     * 蓝牙初始化
     *
     * @param act
     * @return 蓝牙是否已经开启，开启为true，未开启false
     */
    private void bluetoothInit(Activity act) {
        if (!mBluetoothAdapter.isEnabled()) {// 请求打开蓝牙
            openBluetooth(act);
            return;
        }
        // 获取目前已经配对过的设备
        Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
        Iterator<BluetoothDevice> iterator = devices.iterator();

        mPairedDevices = new ArrayList<BluetoothDevice>();
        while (iterator.hasNext()) {
            mPairedDevices.add(iterator.next());
        }
        // 将配对成功的蓝牙设备回调
        iBluetoothSearch.start(mPairedDevices);
    }

    public boolean isOpenBluetooth() {
        return mBluetoothAdapter.isEnabled();
    }

    private final BroadcastReceiver mBluetoothChange = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED
            System.out.println(intent.toString());
            if (!mBluetoothAdapter.isEnabled()) {
                // 如果蓝牙关闭，则断开与阅卷机的连接
                closeConnectBluetooth();
            }
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // 发现设备的时候执行
                BluetoothDevice device = intent
                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                boolean flag = true;
                for (BluetoothDevice d : mNewDevices) {
                    if (d.getAddress().equals(device.getAddress())) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    mNewDevices.add(device);
                    iBluetoothSearch.found(device);
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
                    .equals(action)) {
                // 查找设备完毕后执行回调
                iBluetoothSearch.complete(mNewDevices);
            } else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
                // 开始扫描
                mNewDevices = new ArrayList<BluetoothDevice>();
            }
        }
    };

    /**
     * 开启蓝牙广播搜索
     */
    public void searchBluetooh() {
        IntentFilter requestFilter = new IntentFilter(
                BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        mContext.registerReceiver(mReceiver, requestFilter);

        // Register for broadcasts when a device is discovered
        IntentFilter discoveryFilter = new IntentFilter(
                BluetoothDevice.ACTION_FOUND);
        mContext.registerReceiver(mReceiver, discoveryFilter);

        // Register for broadcasts when discovery has finished
        IntentFilter foundFilter = new IntentFilter(
                BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        mContext.registerReceiver(mReceiver, foundFilter);

        mBluetoothAdapter.startDiscovery();
        isOpenBroadcast = true;
    }

    /**
     * 开启客户端线程
     *
     * @author pf
     * @date 2014-12-4
     */
    @SuppressLint("NewApi")
    private class ClientThread extends Thread {
        public void run() {
            try {
                BluetoothConnector bluetoothConnector = new BluetoothConnector(
                        mConnDevice, false, mBluetoothAdapter, null);
                mBluetoothSocket = bluetoothConnector.connect();
                // 不抛异常，到这里证明连接成功
                isConn = true;
                mReadable = true;
                handler.sendEmptyMessage(CONN_BLUETOOTH_STATUS);
                // 启动接受数据
                mReadThread = new ReadThread();
                mReadThread.start();
            } catch (Exception e) {
                // 处理连接失败。
                Message msg = handler.obtainMessage(CONN_BLUETOOTH_FAILURE, e);
                handler.sendMessage(msg);
            }
        }
    }

    /**
     * 停止客户端连接
     */
    private void shutdownClient() {
        mReadable = false;
        if (mInputStream != null) {
            mInputStream = null;
        }
        if (mBluetoothSocket != null) {
            try {
                mBluetoothSocket.close();
                mBluetoothSocket = null;
            } catch (IOException e) {
                Log.e(TAG, "停止客户端连接发生异常!", e);
            }
        }
    }

    private OutputStream mOutputStream;

    /**
     * 发送命令
     *
     * @param command
     * @return
     */
    public boolean sendCommand(byte[] command) {
        if (mOutputStream == null) {
            return false;
        }
        try {
            mOutputStream.write(command);
            mOutputStream.flush();
            return true;
        } catch (IOException e) {
            LogUtil.e("写入命令失败 command = " + command, e);
            return false;
        }
    }

    // 倒计时20s
    private int mTiming = 20;
    private Timer mTimer;

    /**
     * 定时获取消息
     */
    private Timer connStatusListener() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                mTiming -= 1;
                if (mTiming <= 0) {// 倒计时结束
                    sendCommand(BluetoothCommand.DETECTION_MACHINE);
                }
                if (mTiming <= -10) {// 如果尝试发送10次DETECTION_MACHINE命令都没有收到回复，则认为已经断开
                    closeConnectBluetooth();
                }
            }
        }, 0, 1000);
        return timer;
    }

    /**
     * 读取数据的线程
     *
     * @author pf
     * @date 2014-12-4
     */
    private class ReadThread extends Thread {
        public void run() {
            mTiming = 20;
            byte[] buffer = new byte[1024];
            final List<Byte> totalBytes = new ArrayList<Byte>();
            int bytes;
            try {
                mInputStream = mBluetoothSocket.getInputStream();
                mOutputStream = mBluetoothSocket.getOutputStream();
                if (mTimer != null) {
                    mTimer.cancel();
                }
                mTimer = connStatusListener();
                while (mReadable) {
                    // Read from the InputStream
                    if ((bytes = mInputStream.read(buffer)) > 0) {
                        for (int i = 0; i < bytes; i++) {
                            totalBytes.add(buffer[i]);
                        }
                        // 校验卡
                        // 校验头数据
                        String ahIsB = Integer.toHexString(totalBytes.get(0));
                        // 校验尾数据
                        String aeIsE = Integer.toHexString(totalBytes
                                .get(totalBytes.size() - 1));
                        if (ahIsB.toUpperCase().equals("B")
                                && aeIsE.toUpperCase().equals("E")) {
                            mTiming = 20;
                            int dataLen = totalBytes.get(2) & 0xFF;
                            System.out.println(dataLen + ":"
                                    + (totalBytes.size() - 4));
                            if (dataLen == (totalBytes.size() - 4)) {// 数据正确
                                System.out.println(1);
                                if (dataLen == 3) {
                                    System.out.println(2);
                                    // 向前退卡，向后退卡，阅卷机是否有卡的响应数据
                                } else {
                                    System.out.println(3);
                                    int line = dataLen / 2;
                                    List<Byte> validDatas = totalBytes.subList(
                                            3, totalBytes.size() - 5);
                                    if (line == SheetType.S1300_SHEET_56x13.line) {
                                        // 13*56
                                        Map<String, Object> sheetMap = Parse56x16Util
                                                .byteToMap(validDatas);
                                        Message msg = getHandlerMsg(sheetMap,
                                                SheetType.S1300_SHEET_56x13);
                                        handler.sendMessage(msg);
                                    } else if (line == SheetType.S1300_SHEET_61x13.line) {
                                        // 13*61
                                        Map<String, Object> sheetMap = Parse61x16Util
                                                .byteToMap(validDatas);
                                        Message msg = getHandlerMsg(sheetMap,
                                                SheetType.S1300_SHEET_61x13);
                                        handler.sendMessage(msg);
                                    } else if (line == SheetType.S1300_SHEET_40x13.line) {
                                        // 13*40
                                        Map<String, Object> sheetMap = Parse40x16Util
                                                .byteToMap(validDatas);
                                        Message msg = getHandlerMsg(sheetMap,
                                                SheetType.S1300_SHEET_40x13);
                                        handler.sendMessage(msg);
                                    } else {
                                        // 处理没有找到的答题卡类型
                                        handler.sendEmptyMessage(NOT_FOUND_SHEET);
                                    }
                                }
                            } else {// 数据错误
                                System.out.println(4);
                                handler.sendEmptyMessage(READ_CARD_FAILURE);
                            }
                            totalBytes.clear();
                        }
                        if (!ahIsB.toUpperCase().equals("B")) {
                            totalBytes.clear();
                        }
                    }
                }
            } catch (IOException e) {
                // LogUtils.e("IO流异常", e);
            } finally {
                try {
                    if (mInputStream != null) {
                        mInputStream.close();
                        mInputStream = null;
                    }
                    if (mOutputStream != null) {
                        mOutputStream.close();
                        mOutputStream = null;
                    }
                } catch (IOException e) {
                    Log.e(TAG, "关闭输入流mInputStream异常", e);
                }

            }
        }

        private Message getHandlerMsg(Map<String, Object> sheetMap,
                                      SheetType sheetType) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(SHEET_DATA, sheetMap);
            map.put(SHEET_TYPE, sheetType);
            Message msg = handler.obtainMessage(READ_CARD_SUCCESS, map);
            return msg;
        }
    }

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {
        @SuppressWarnings({"unchecked"})
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONN_BLUETOOTH_STATUS:
                    // 发送一条信息，连接蓝牙成功
                    iBluetoothStatus.connBluetoonthChange(isConn);
                    break;
                case CONN_BLUETOOTH_FAILURE:
                    // 处理连接失败。
                    iBluetoothStatus.connBluetoonthFailure(isConn,
                            (Exception) msg.obj);
                    break;
                case READ_CARD_SUCCESS:
                    // 处理读卡成功
                    Map<String, Object> map = (Map<String, Object>) msg.obj;
                    Map<String, Object> sheetData = (Map<String, Object>) map
                            .get(SHEET_DATA);
                    SheetType sheetType = (SheetType) map.get(SHEET_TYPE);
                    iReadCard.readSuccess(sheetType, sheetData);
                    break;
                case READ_CARD_FAILURE:
                    // 处理读卡失败
                    iReadCard.readFailure();
                    break;
                case NOT_FOUND_SHEET:
                    // 处理未找到答题卡类型
                    iReadCard.notFoundSheet();
                    break;
                default:
                    break;
            }
        }
    };

}